package gateway

import (
	"bytes"
	"fmt"
	"github.com/hyperledger/fabric/common/tools/protolator"
	"github.com/hyperledger/fabric/protos/common"
	putils "github.com/hyperledger/fabric/protos/utils"
)

type Certificate interface {
	GetTlsCert() []byte
}


type PeerContext struct {
	Host        string
	ServiceName string
	RootTLSCert []byte
}

func (peer PeerContext) client() (*peerClient, error) {
	//return newPeerCient(peer.Host, peer.ServiceName, peer.RootTLSCert)
	return newPeerClientWithTLSBytes(peer.Host, peer.ServiceName, peer.RootTLSCert)
}

type OrdererContext struct {
	Host        string
	ServiceName string
	RootTLSCert []byte
}

func (orderer OrdererContext) client() (*ordererClient, error) {
	//return newOrdererClient(orderer.Host, orderer.ServiceName, orderer.RootTLSCert)
	return newOrdererClientWithTlsBytes(orderer.Host, orderer.ServiceName, orderer.RootTLSCert)
}

type BlockChainInfo struct {
	ChannelID  string
	Height  uint64
	PreviousBlockHash  string
	CurrentBlockHash  string
}

type BlockInfo struct {
	Number       uint64
	PreBlockHash string
	DataHash     string
	Signature  []byte
	CommitHash []byte
	Payload  []byte
}

func ExtractBlock(b *common.Block) (*BlockInfo, error) {
	blockInfo := &BlockInfo{
		Number:       b.Header.Number,
		PreBlockHash: HashToString(b.Header.PreviousHash),
		DataHash:     HashToString(b.Header.DataHash),
	}
	sign, _ := putils.GetMetadataFromBlock(b, common.BlockMetadataIndex_SIGNATURES)
	blockInfo.Signature = sign.Value

	hash, _ := putils.GetMetadataFromBlock(b, common.BlockMetadataIndex_COMMIT_HASH)
	blockInfo.CommitHash = hash.Value

	fmt.Println("data length:", len(b.Data.Data))
	env, err := putils.GetEnvelopeFromBlock(b.Data.Data[0])
	if err != nil {
		return nil, err
	}
	payload, _ := putils.GetPayload(env)

	data := bytes.NewBuffer([]byte(""))
	err = protolator.DeepMarshalJSON(data, payload)
	if err != nil {
		blockInfo.Payload = []byte(err.Error())
	} else {
		blockInfo.Payload = data.Bytes()
	}
	return blockInfo, nil
}

func HashToString(data []byte) string {
	return fmt.Sprintf("%x", data)
}

type ChainCodeListResponse struct {
	Count int
	ChainCodes []ChaincodeInfo
}

type ChainCodeQueryResponse struct {
	Payload []byte
	Message string
	Status int32
}

type BlockSummary struct {
	Number  uint64
	PreHash  string
	DataHash string
}

type ChainCodeInvokeResponse struct {
	Statue int
	Message string
	TxID  string
	ProposalHash []byte
	Result []byte
	TxTime string
}